Terraform Stacksの構成要素を図解してみる
HashiConf 2024でTerraform Stacksがパブリックベータになりました。
Terraform Stacksによって新しい構成要素がいくつか追加されたので、できるだけ図を使って説明していきます。
Terraform Stacksとは
Stacks are a powerful configuration layer in HCP Terraform that simplifies managing your infrastructure modules and then repeating that infrastructure.
スタックは、インフラストラクチャ モジュールの管理とそのインフラストラクチャの繰り返しを簡素化する、HCP Terraform の強力な構成レイヤーです。
Stacks Overview | Terraform | HashiCorp Developerから引用
ざっくり説明すると、複数Workspaceが必要な構成を、簡単に作れる機能です。
例えば以下のケースでは、複数のWorkspaceを必要とします。
- 本番、ステージング、開発等 同一構成の複数環境を構築する
- 複数リージョンに同一構成の環境を構築する
- Multiple Provider Configurations不使用でStatefileを分割するパターン
- Kubernetesワークロードを構築する
- CRDを登録して、カスタムリソースを作成する等
個別にWorkspaceを作る場合、それぞれVCSやトリガーの設定等を行う必要があります。
Terraform Stacksを使って構成することで、この手間を削減できます。
本番・ステージング・開発の3環境を作る場合、WorkspaceとStacks構成のイメージは以下です。
StacksはProject配下に作成します。Deploymentsという単位で、State管理・Terraform実行されます。
Workspaceのように、HCP Terraform上のVariablesはありません。環境毎に異なる値は、コード上で指定する形になります。
注意点
現時点では、HCP Terraformで利用可能です。一部の機能はコミュニティ版にも組み込まれる予定とのことです。
現時点では、500 Resouceまでの制限があるため、合わせてご注意ください。(有償プランを契約している場合も同様です)
While our public beta is limited to HCP Terraform plans based on resources under management (RUM), certain Stacks functionality will be incorporated in upcoming releases of the community edition of Terraform.
Terraform Stacksの構成要素
Terraform Stacksの構成要素は以下の4つです。
- Components
- Deployments
- Orchestration rules
- Deferred changes
Stacksを利用するには、ComponentsとDeploymentsは必須です。
Orchestration rulesとDeferred changesは設定しなくても、Terraform Stacksを利用することは可能です。
API Gateway + Lambda + S3の構成をPROD・STG・DEVの3環境作成を例に、Terraform Stacksを説明します。
Components
スタックに含めるリソースを定義します。
tfstack.hcl
という拡張子でファイルを作成し、component
ブロックを定義します。
component
ブロックでは、モジュールやプロバイダーを指定します。(以下、s3用のComponentsです)
component "s3" {
for_each = var.regions
source = "./s3"
inputs = {
region = each.value
}
providers = {
aws = provider.aws.configurations[each.value]
random = provider.random.this
}
}
注意点として、モジュールは現時点(2024/10時点)では、プライベートレジストリからのモジュールはサポートしていません。(パブリックレジストリはサポートしている)
ちなみに、providerもファイル拡張子tfstack.hcl
で定義します。
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.7.0"
}
}
provider "aws" "configurations" {
for_each = var.regions
config {
region = each.value
assume_role_with_web_identity {
role_arn = var.role_arn
web_identity_token = var.identity_token
}
}
}
Deployments
デプロイする場所を定義します。(AWSなら、AWSアカウント・リージョン等)
tfdeploy.hcl
という拡張子でファイルを作成し、deployment
ブロックを定義します。
Terraform実行用のIAMロールや対象リージョンを指定します。
PROD・STG・DEVの3環境を用意するため、それぞれdeployment
ブロックを定義しています。
identity_token "aws" {
audience = ["aws.workload.identity"]
}
deployment "prod" {
inputs = {
regions = ["us-east-1", "us-west-1"]
role_arn = "<PRDアカウント IAM Role ARN>"
identity_token = identity_token.aws.jwt
}
}
deployment "stg" {
inputs = {
regions = ["us-east-1", "us-west-1"]
role_arn = "<STGアカウント IAM Role ARN>"
identity_token = identity_token.aws.jwt
}
}
deployment "dev" {
inputs = {
regions = ["us-east-1"]
role_arn = "<DEVアカウント IAM Role ARN>"
identity_token = identity_token.aws.jwt
}
}
identity_token
ブロックは、jwtトークンを生成します。
provider定義で以下のようにjwtトークンとIAMロールを受け取っています。
# 省略
provider "aws" "configurations" {
for_each = var.regions
config {
region = each.value
assume_role_with_web_identity {
role_arn = var.role_arn
web_identity_token = var.identity_token
}
}
}
Orchestration rules
Deploymentsの管理に使用できるルールを定義できます。
現時点では、2つのルールがサポートされており、チェックに合格時に以下の動作が行われます。
- auto_approve: 自動承認(承認時に
terraform apply
相当が行われる) - replan: Planを再実行
以下のルールは、Planの内容に削除が含まれていなければ、自動的にPlanを承認します。
orchestrate "auto_approve" “safe_plans” {
check {
#check that there are no resources being removed
condition = context.plan.changes.remove == 0
reason = "Plan has ${context,plan.changes. remove} resources to be removed."
}
}
Deferred changes
Componentsの依存関係を管理する機能です。
例えば、カスタムリソースを使うKubernetesワークロードを管理するケースを考えます。
CRDが存在しない状態でカスタムリソースを作成することはできないので、これは一つの手順で行うことができません。
そのため、CRDを登録が終わった後にカスタムリソース作成をする必要があります。
以下で、component.cluster
とcomponent.kube
を依存関係を指定できます。
component "cluster" {
source = "./cluster"
providers = {
aws = provider.aws.main
random = provider.random.main
}
inputs = {
cluster_name = var.cluster_name
kubernetes_version = var.kubernetes_version
region = var.region
}
}
component "kube" {
source = "./kube"
providers = {
kubernetes = provider.kubernetes.main
}
}
provider "kubernetes" "main" {
config {
host = component.cluster.cluster_url
cluster_ca_certificate = component.cluster.cluster_ca
token = component.cluster.cluster_token
}
}
provider.kubernetes.main
でcomponent.cluster
の出力値を指定しているため、依存関係を解釈して自動的にcomponent.kube
の実行を延期します。
おわりに
Terraform Stacksの概要部分の説明でした。この後チュートリアルやってみたブログも公開する予定です。
実際の画面のイメージは以下のブログを参照いただくと良さそうです。
以上、AWS事業本部の佐藤(@chari7311)でした。